package com.asen.commons.core.meta.dao;

import com.asen.commons.core.meta.enums.FilterRelationEnum;
import com.asen.commons.core.meta.enums.FilterSymbolEnum;
import com.asen.commons.utils.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * 条件组合
 *
 * @author ls
 * @version 1.0
 * @date 2024-04-09
 */
public class FilterGroup {

    private FilterRelationEnum filterRelation = FilterRelationEnum.AND;

    private List<FilterGroup> filterGroups = new ArrayList<FilterGroup>();

    private List<FilterItem> filterItems = new ArrayList<FilterItem>();

    public FilterGroup() {
    }

    public FilterGroup(FilterRelationEnum filterRelation) {
        this.filterRelation = filterRelation;
    }

    /**
     * 重置比较条件
     */
    public void reset() {
        filterRelation = FilterRelationEnum.AND;
        filterGroups.clear();
        filterItems.clear();
    }

    /**
     * 等于比较，参考SQL比较语句如：fieldName = value
     *
     * @param fieldName
     * @param value
     */
    public void equal(String fieldName, Object value) {
        addFilterItem(fieldName, FilterSymbolEnum.EQUAL, value);
    }

    /**
     * 不等于比较，参考SQL比较语句如：fieldName <> value
     *
     * @param fieldName
     * @param value
     */
    public void notEqual(String fieldName, Object value) {
        addFilterItem(fieldName, FilterSymbolEnum.NOT_EQUAL, value);
    }

    /**
     * 大于比较，参考SQL比较语句如：fieldName > value
     *
     * @param fieldName
     * @param value
     */
    public void greater(String fieldName, Object value) {
        addFilterItem(fieldName, FilterSymbolEnum.GREATER, value);
    }

    /**
     * 小于比较，参考SQL比较语句如：fieldName < value
     *
     * @param fieldName
     * @param value
     */
    public void less(String fieldName, Object value) {
        addFilterItem(fieldName, FilterSymbolEnum.LESS, value);
    }

    /**
     * 大于等于比较，参考SQL比较语句如：fieldName >= value
     *
     * @param fieldName
     * @param value
     */
    public void greaterEqual(String fieldName, Object value) {
        addFilterItem(fieldName, FilterSymbolEnum.GREATER_EQUAL, value);
    }

    /**
     * 小于等于比较，参考SQL比较语句如：fieldName <= value
     *
     * @param fieldName
     * @param value
     */
    public void lessEqual(String fieldName, Object value) {
        addFilterItem(fieldName, FilterSymbolEnum.LESS_EQUAL, value);
    }

    /**
     * 模糊匹配，参考SQL比较语句如：fieldName LIKE %value%
     *
     * @param fieldName
     * @param value
     */
    public void like(String fieldName, Object value) {
        addFilterItem(fieldName, FilterSymbolEnum.LIKE, value);
    }

    /**
     * 模糊匹配，参考SQL比较语句如：fieldName NOT LIKE %value%
     *
     * @param fieldName
     * @param value
     */
    public void notLike(String fieldName, Object value) {
        addFilterItem(fieldName, FilterSymbolEnum.NOT_LIKE, value);
    }

    /**
     * 左类似模糊匹配，参考SQL比较语句如：fieldName LIKE value%
     *
     * @param fieldName
     * @param value
     */
    public void leftLike(String fieldName, Object value) {
        addFilterItem(fieldName, FilterSymbolEnum.LEFT_LIKE, value);
    }

    /**
     * 非左类似模糊匹配，参考SQL比较语句如：not LIKE XXX%
     *
     * @param fieldName
     * @param value
     */
    public void notLeftLike(String fieldName, Object value) {
        addFilterItem(fieldName, FilterSymbolEnum.NOT_LEFT_LIKE, value);
    }

    /**
     * 右类似模糊匹配，参考SQL比较语句如：fieldName LIKE %value
     *
     * @param fieldName
     * @param value
     */
    public void rightLike(String fieldName, Object value) {
        addFilterItem(fieldName, FilterSymbolEnum.RIGHT_LIKE, value);
    }

    /**
     * 非右类似模糊匹配，参考SQL比较语句如：fieldName NOT LIKE %value
     *
     * @param fieldName
     * @param value
     */
    public void notRightLike(String fieldName, Object value) {
        addFilterItem(fieldName, FilterSymbolEnum.NOT_RIGHT_LIKE, value);
    }

    /**
     * 判断是否为null，参考SQL比较语句如：fieldName IS NULL
     *
     * @param fieldName
     */
    public void isNull(String fieldName) {
        FilterItem item = new FilterItem(fieldName, FilterSymbolEnum.IS_NULL, null);

        if (filterItems.contains(item)) {
            return;
        }

        filterItems.add(item);
    }

    /**
     * 判断是否为not null，参考SQL比较语句如：fieldName IS NOT NULL
     *
     * @param fieldName
     */
    public void isNotNull(String fieldName) {
        FilterItem item = new FilterItem(fieldName, FilterSymbolEnum.IS_NOT_NULL, null);

        if (filterItems.contains(item)) {
            return;
        }

        filterItems.add(item);
    }

    /**
     * 包含关系比较，参考SQL比较语句如：fieldName IN (value1, value2, ...)
     *
     * @param fieldName
     * @param value
     * @param <V>
     */
    public <V> void in(String fieldName, V[] value) {
        if (ArrayUtils.isEmpty(value)) {
            return;
        }

        addFilterItem(fieldName, FilterSymbolEnum.IN, value);
    }

    /**
     * 包含关系比较，参考SQL比较语句如：fieldName IN (value1, value2, ...)
     *
     * @param fieldName
     * @param value
     */
    public void in(String fieldName, Collection<?> value) {
        if (CollectionUtils.isEmpty(value)) {
            return;
        }

        addFilterItem(fieldName, FilterSymbolEnum.IN, value);
    }

    /**
     * 包含关系比较，参考SQL比较语句如：fieldName NOT IN (value1, value2, ...)
     *
     * @param fieldName
     * @param value
     * @param <V>
     */
    public <V> void notIn(String fieldName, V[] value) {
        if (ArrayUtils.isEmpty(value)) {
            return;
        }

        addFilterItem(fieldName, FilterSymbolEnum.NOT_IN, value);
    }

    /**
     * 包含关系比较，参考SQL比较语句如：fieldName NOT IN (value1, value2, ...)
     *
     * @param fieldName
     * @param value
     */
    public void notIn(String fieldName, Collection<?> value) {
        if (CollectionUtils.isEmpty(value)) {
            return;
        }

        addFilterItem(fieldName, FilterSymbolEnum.NOT_IN, value);
    }

    /**
     * 两个字段的比较，参考SQL比较语句如：fieldName1 = fieldName2
     *
     * @param fieldName1
     * @param fieldName2
     */
    public void compareEqual(String fieldName1, String fieldName2) {
        FilterItem item = new FilterItem();
        item.setFieldName(fieldName1);
        item.setFieldName2(fieldName2);
        item.setSymbol(FilterSymbolEnum.COMPARE_EQUAL);
        if (filterItems.contains(item)) {
            return;
        }
        filterItems.add(item);
    }

    /**
     * 支持数值类型（如：Integer/BigDecimal）的比较
     *
     * @param fieldName1
     * @param fieldName2
     * @param value
     */
    public void compareGreater(String fieldName1, String fieldName2, Object value) {
        FilterItem item = new FilterItem();
        item.setFieldName(fieldName1);
        item.setFieldName2(fieldName2);
        item.setSymbol(FilterSymbolEnum.COMPARE_GREATER);
        item.setValue(value);
        if (filterItems.contains(item)) {
            return;
        }
        filterItems.add(item);
    }

    /**
     * 支持数值类型（如：Integer/BigDecimal）的比较
     *
     * @param fieldName1
     * @param fieldName2
     * @param value
     */
    public void compareGreaterEqual(String fieldName1, String fieldName2, Object value) {
        FilterItem item = new FilterItem();
        item.setFieldName(fieldName1);
        item.setFieldName2(fieldName2);
        item.setSymbol(FilterSymbolEnum.COMPARE_GREATER_EQUAL);
        item.setValue(value);
        if (filterItems.contains(item)) {
            return;
        }
        filterItems.add(item);
    }

    /**
     * 支持数值类型（如：Integer/BigDecimal）的比较
     *
     * @param fieldName1
     * @param fieldName2
     * @param value
     */
    public void compareLess(String fieldName1, String fieldName2, Object value) {
        FilterItem item = new FilterItem();
        item.setFieldName(fieldName1);
        item.setFieldName2(fieldName2);
        item.setSymbol(FilterSymbolEnum.COMPARE_LESS);
        item.setValue(value);
        if (filterItems.contains(item)) {
            return;
        }
        filterItems.add(item);
    }

    /**
     * 支持数值类型（如：Integer/BigDecimal）的比较
     *
     * @param fieldName1
     * @param fieldName2
     * @param value
     */
    public void compareLessEqual(String fieldName1, String fieldName2, Object value) {
        FilterItem item = new FilterItem();
        item.setFieldName(fieldName1);
        item.setFieldName2(fieldName2);
        item.setSymbol(FilterSymbolEnum.COMPARE_LESS_EQUAL);
        item.setValue(value);
        if (filterItems.contains(item)) {
            return;
        }
        filterItems.add(item);
    }

    /**
     * 两个字段的比较条件，fieldName1 != fieldName2
     *
     * @param fieldName1
     * @param fieldName2
     */
    public void compareNotEqual(String fieldName1, String fieldName2) {
        FilterItem item = new FilterItem();
        item.setFieldName(fieldName1);
        item.setFieldName2(fieldName2);
        item.setSymbol(FilterSymbolEnum.COMPARE_NOT_EQUAL);
        if (filterItems.contains(item)) {
            return;
        }
        filterItems.add(item);
    }

    /**
     * 两个字段的比较条件，fieldName1 = fieldName2 (取绝对值比较)
     *
     * @param fieldName1
     * @param fieldName2
     */
    public void compareEqualAbs(String fieldName1, String fieldName2) {
        FilterItem item = new FilterItem();
        item.setFieldName(fieldName1);
        item.setFieldName2(fieldName2);
        item.setSymbol(FilterSymbolEnum.COMPARE_EQUAL_ABS);
        if (filterItems.contains(item)) {
            return;
        }
        filterItems.add(item);
    }

    /**
     * 支持数值类型（如：Integer/BigDecimal）的比较 (取绝对值比较)
     *
     * @param fieldName1
     * @param fieldName2
     * @param value
     */
    public void compareGreaterAbs(String fieldName1, String fieldName2, Object value) {
        FilterItem item = new FilterItem();
        item.setFieldName(fieldName1);
        item.setFieldName2(fieldName2);
        item.setSymbol(FilterSymbolEnum.COMPARE_GREATER_ABS);
        item.setValue(value);
        if (filterItems.contains(item)) {
            return;
        }
        filterItems.add(item);
    }

    /**
     * 支持数值类型（如：Integer/BigDecimal）的比较 (取绝对值比较)
     *
     * @param fieldName1
     * @param fieldName2
     * @param value
     */
    public void compareGreaterEqualAbs(String fieldName1, String fieldName2, Object value) {
        FilterItem item = new FilterItem();
        item.setFieldName(fieldName1);
        item.setFieldName2(fieldName2);
        item.setSymbol(FilterSymbolEnum.COMPARE_GREATER_EQUAL_ABS);
        item.setValue(value);
        if (filterItems.contains(item)) {
            return;
        }
        filterItems.add(item);
    }

    /**
     * 支持数值类型（如：Integer/BigDecimal）的比较 (取绝对值比较)
     *
     * @param fieldName1
     * @param fieldName2
     * @param value
     */
    public void compareLessAbs(String fieldName1, String fieldName2, Object value) {
        FilterItem item = new FilterItem();
        item.setFieldName(fieldName1);
        item.setFieldName2(fieldName2);
        item.setSymbol(FilterSymbolEnum.COMPARE_LESS_ABS);
        item.setValue(value);
        if (filterItems.contains(item)) {
            return;
        }
        filterItems.add(item);
    }

    /**
     * 支持数值类型（如：Integer/BigDecimal）的比较 (取绝对值比较)
     *
     * @param fieldName1
     * @param fieldName2
     * @param value
     */
    public void compareLessEqualAbs(String fieldName1, String fieldName2, Object value) {
        FilterItem item = new FilterItem();
        item.setFieldName(fieldName1);
        item.setFieldName2(fieldName2);
        item.setSymbol(FilterSymbolEnum.COMPARE_LESS_EQUAL_ABS);
        item.setValue(value);
        if (filterItems.contains(item)) {
            return;
        }
        filterItems.add(item);
    }

    /**
     * 两个字段的比较条件，fieldName1 != fieldName2 (取绝对值比较)
     *
     * @param fieldName1
     * @param fieldName2
     */
    public void compareNotEqualAbs(String fieldName1, String fieldName2) {
        FilterItem item = new FilterItem();
        item.setFieldName(fieldName1);
        item.setFieldName2(fieldName2);
        item.setSymbol(FilterSymbolEnum.COMPARE_NOT_EQUAL_ABS);
        if (filterItems.contains(item)) {
            return;
        }
        filterItems.add(item);
    }

    /**
     * 两个字段的比较条件，fieldName1 - fieldName2 = value
     *
     * @param fieldName1
     * @param fieldName2
     */
    public void compareEqualValue(String fieldName1, String fieldName2, Object value) {
        FilterItem item = new FilterItem();
        item.setFieldName(fieldName1);
        item.setFieldName2(fieldName2);
        item.setSymbol(FilterSymbolEnum.COMPARE_EQUAL_VALUE);
        item.setValue(value);
        if (filterItems.contains(item)) {
            return;
        }
        filterItems.add(item);
    }

    /**
     * 两个字段的比较条件，fieldName1 - fieldName2 != value
     *
     * @param fieldName1
     * @param fieldName2
     */
    public void compareNotEqualValue(String fieldName1, String fieldName2, Object value) {
        FilterItem item = new FilterItem();
        item.setFieldName(fieldName1);
        item.setFieldName2(fieldName2);
        item.setSymbol(FilterSymbolEnum.COMPARE_NOT_EQUAL_VALUE);
        item.setValue(value);
        if (filterItems.contains(item)) {
            return;
        }
        filterItems.add(item);
    }

    /**
     * 两个字段的比较条件，fieldName1 - fieldName2 = value (取绝对值比较)
     *
     * @param fieldName1
     * @param fieldName2
     */
    public void compareEqualValueAbs(String fieldName1, String fieldName2, Object value) {
        FilterItem item = new FilterItem();
        item.setFieldName(fieldName1);
        item.setFieldName2(fieldName2);
        item.setSymbol(FilterSymbolEnum.COMPARE_EQUAL_VALUE_ABS);
        item.setValue(value);
        if (filterItems.contains(item)) {
            return;
        }
        filterItems.add(item);
    }

    /**
     * 两个字段的比较条件，fieldName1 - fieldName2 != value (取绝对值比较)
     *
     * @param fieldName1
     * @param fieldName2
     */
    public void compareNotEqualValueAbs(String fieldName1, String fieldName2, Object value) {
        FilterItem item = new FilterItem();
        item.setFieldName(fieldName1);
        item.setFieldName2(fieldName2);
        item.setSymbol(FilterSymbolEnum.COMPARE_NOT_EQUAL_VALUE_ABS);
        item.setValue(value);
        if (filterItems.contains(item)) {
            return;
        }
        filterItems.add(item);
    }

    /**
     * 等于比较(忽略大小写)，参考SQL比较语句如：upper(fieldName) = upper(value)
     */
    public void equalIgnoreCase(String fieldName, Object value) {
        addFilterItem(fieldName, FilterSymbolEnum.EQUAL_IGNORE_CASE, value);
    }

    /**
     * 模糊匹配(忽略大小写)，参考SQL比较语句如：upper(fieldName) LIKE concat('%', upper(value), '%')
     */
    public void likeIgnoreCase(String fieldName, Object value) {
        addFilterItem(fieldName, FilterSymbolEnum.LIKE_IGNORE_CASE, value);
    }

    /**
     * 自定义条件项，支持复杂条件项sql或表达式，实体属性以${XXX}格式引用
     * 如：condition.custom("${bizType} = case when ${type} in (1, 2, 3) then '02' else '01' end")
     *
     * @param value
     */
    public void custom(String value) {
        addFilterItem("", FilterSymbolEnum.CUSTOM, value);
    }

    /**
     * 添加比较项
     *
     * @param fieldName
     * @param symbol
     * @param value     比较值为空时，则忽略
     */
    public void addFilterItem(String fieldName, FilterSymbolEnum symbol, Object value) {
        if (value == null) {
            return;
        }

        if (value instanceof String) {
            if (StringUtils.isEmpty(value.toString())) {
                return;
            }
        }

        FilterItem item = new FilterItem(fieldName, symbol, value);

        if (filterItems.contains(item)) {
            return;
        }

        filterItems.add(item);
    }

    /**
     * 删除过滤条件项
     *
     * @param item
     */
    public void removeFilterItem(FilterItem item) {
        filterItems.remove(item);
    }

    /**
     * 删除所有fieldName相关的条件项
     *
     * @param fieldName
     */
    public void removeFilterItem(String fieldName) {
        if (fieldName == null) {
            return;
        }

        filterItems.removeIf(x -> x.getFieldName().equals(fieldName));
    }

    public List<FilterItem> getFilterItems() {
        return filterItems;
    }

    public void addFilterGroup(FilterGroup filterGroup) {
        this.filterGroups.add(filterGroup);
    }

    public void setFilterItems(List<FilterItem> filterItems) {
        this.filterItems = filterItems;
    }

    public void setFilterGroups(List<FilterGroup> filterGroups) {
        this.filterGroups = filterGroups;
    }

    public List<FilterGroup> getFilterGroups() {
        return filterGroups;
    }

    public void setFilterRelation(FilterRelationEnum filterRelation) {
        this.filterRelation = filterRelation;
    }

    public FilterRelationEnum getFilterRelation() {
        return filterRelation;
    }

}
